<?php

namespace Upfor\UpforPHP\Library;

use DirectoryIterator;
use FilesystemIterator;

/**
 * File system
 */
class FileSystem {

    /**
     * Mime types
     *
     * @var array
     */
    protected static $mimeTypes =
        [
            'aac' => 'audio/aac',
            'atom' => 'application/atom+xml',
            'avi' => 'video/avi',
            'bmp' => 'image/x-ms-bmp',
            'c' => 'text/x-c',
            'class' => 'application/octet-stream',
            'css' => 'text/css',
            'csv' => 'text/csv',
            'deb' => 'application/x-deb',
            'dll' => 'application/x-msdownload',
            'dmg' => 'application/x-apple-diskimage',
            'doc' => 'application/msword',
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'exe' => 'application/octet-stream',
            'flv' => 'video/x-flv',
            'gif' => 'image/gif',
            'gz' => 'application/x-gzip',
            'h' => 'text/x-c',
            'htm' => 'text/html',
            'html' => 'text/html',
            'ics' => 'text/calendar',
            'ical' => 'text/calendar',
            'ini' => 'text/plain',
            'jar' => 'application/java-archive',
            'java' => 'text/x-java',
            'jpeg' => 'image/jpeg',
            'jpg' => 'image/jpeg',
            'js' => 'text/javascript',
            'json' => 'application/json',
            'jp2' => 'image/jp2',
            'mid' => 'audio/midi',
            'midi' => 'audio/midi',
            'mka' => 'audio/x-matroska',
            'mkv' => 'video/x-matroska',
            'mp3' => 'audio/mpeg',
            'mp4' => 'video/mp4',
            'mpeg' => 'video/mpeg',
            'mpg' => 'video/mpeg',
            'm4a' => 'video/mp4',
            'm4v' => 'video/mp4',
            'odt' => 'application/vnd.oasis.opendocument.text',
            'ogg' => 'audio/ogg',
            'pdf' => 'application/pdf',
            'php' => 'text/x-php',
            'png' => 'image/png',
            'psd' => 'image/vnd.adobe.photoshop',
            'py' => 'application/x-python',
            'ra' => 'audio/vnd.rn-realaudio',
            'ram' => 'audio/vnd.rn-realaudio',
            'rar' => 'application/x-rar-compressed',
            'rss' => 'application/rss+xml',
            'safariextz' => 'application/x-safari-extension',
            'sh' => 'text/x-shellscript',
            'shtml' => 'text/html',
            'swf' => 'application/x-shockwave-flash',
            'tar' => 'application/x-tar',
            'tif' => 'image/tiff',
            'tiff' => 'image/tiff',
            'torrent' => 'application/x-bittorrent',
            'txt' => 'text/plain',
            'wav' => 'audio/wav',
            'webp' => 'image/webp',
            'wma' => 'audio/x-ms-wma',
            'xls' => 'application/vnd.ms-excel',
            'xml' => 'text/xml',
            'zip' => 'application/zip',
            '3gp' => 'video/3gpp',
            '3g2' => 'video/3gpp2',
        ];

    /**
     * Returns TRUE if a file or directory is empty and FALSE if not
     *
     * @param  string $path Path to directory
     * @return boolean
     */
    public static function isEmpty($path) {
        if (is_dir($path)) {
            foreach (new DirectoryIterator($path) as $file) {
                if (!$file->isDot()) {
                    return false;
                }
            }

            return true;
        }

        return filesize($path) === 0;
    }

    /**
     * Returns the time (unix timestamp) the file was last modified
     *
     * @param  string $file Path to file
     * @return integer
     */
    public static function lastModified($file) {
        return filemtime($file);
    }

    /**
     * Returns the extension of the file
     *
     * @param  string $file Path to file
     * @return string
     */
    public static function extension($file) {
        return pathinfo($file, PATHINFO_EXTENSION);
    }

    /**
     * Returns the mime type of the file
     *
     * @param  string  $file  Path to file
     * @param  boolean $guess (optional) Guess mime type if finfo_open doesn't exist?
     * @return string|boolean
     */
    public static function mime($file, $guess = true) {
        if (function_exists('finfo_open')) {
            // Get mime using the file information functions
            $info = finfo_open(FILEINFO_MIME_TYPE);
            $mime = finfo_file($info, $file);
            finfo_close($info);

            return $mime;
        } else {
            if ($guess === true) {
                // Just guess mime by using the file extension
                $extension = pathinfo($file, PATHINFO_EXTENSION);

                return self::$mimeTypes[$extension] ? : false;
            }

            return false;
        }
    }

    /**
     * Deletes a directory and its contents from disk
     *
     * @param  string $path Path to directory
     * @return boolean
     */
    public static function removeDirectory($path) {
        foreach (new FilesystemIterator($path) as $item) {
            if ($item->isDir()) {
                self::removeDirectory($item->getPathname());
            } else {
                unlink($item->getPathname());
            }
        }

        return rmdir($path);
    }

    /**
     * Truncates a file
     *
     * @param  string  $file File path
     * @param  boolean $lock Acquire an exclusive write lock?
     * @return boolean
     */
    public static function truncate($file, $lock = false) {
        return (0 === file_put_contents($file, null, $lock ? LOCK_EX : 0));
    }

}
